#pragma once
#include "rpc_router.hpp"
#include "rpc_register.hpp"
#include "rpc_topic.hpp"
#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"
namespace RPC
{
    namespace Server
    {
        class RegisterServer
        {
        public:
            RegisterServer(int port) : _pdmanager(std::make_shared<PDManager>()), _dispatcher(std::make_shared<Dispatcher>())
            {
                auto req_rpc = std::bind(&PDManager::onServerRequest, _pdmanager.get(), std::placeholders::_1,
                                         std::placeholders::_2);
                auto shutcb = std::bind(&PDManager::onConnShutdown, _pdmanager.get(), std::placeholders::_1);
                _dispatcher->registerCallback<ServiceRequest>(MType::REQ_SERVICE, req_rpc);

                _registerserver = ServerFactory::create(port);
                auto dpcher = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1,
                                        std::placeholders::_2);
                _registerserver->setMessageCallback(dpcher);
                _registerserver->setCloseCallback(shutcb);
            }

            void start()
            {
                INFO_LOG("注册中心开始运行！");
                _registerserver->start();
            }

        private:
            PDManager::Ptr _pdmanager;
            Dispatcher::Ptr _dispatcher;
            BaseServer::Ptr _registerserver;
        };

        class RpcServer
        {
        public:
            RpcServer(const Address &local_addr, bool enableregister = false, const Address &rgster_addr = Address())
                : _address(local_addr), _enableregister(enableregister),
                  _dispatcher(std::make_shared<Dispatcher>()), _router(std::make_shared<RpcRouter>())
            {
                if (_enableregister == true)
                {
                    _register_client = std::make_shared<Client::RegisterClient>(rgster_addr.first, rgster_addr.second);
                }

                auto routercb = std::bind(&RpcRouter::onRpcRequest, _router.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerCallback<RpcRequest>(MType::REQ_RPC, routercb);

                _rpcserver = ServerFactory::create(local_addr.second);
                auto dispchcb = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _rpcserver->setMessageCallback(dispchcb);
            }

            void registerMethod(const ServiceDiscribe::Ptr &service)
            {
                if (_enableregister == true)
                {
                    // 如果当前服务提供者可以提供服务发现，那么就向注册中心注册方法
                    _register_client->registorMethod(_address, service->method());
                }
                // 服务提供者在本地注册方法
                _router->registerRequest(service);
            }

            void start()
            {
                _rpcserver->start();
            }

        private:
            bool _enableregister;                         // 是否启用服务注册
            Client::RegisterClient::Ptr _register_client; // 启用服务注册需要一个客服端连接注册中心

            Address _address;            // 提供服务时本机的地址
            RpcRouter::Ptr _router;      // 用于注册rpc，管理rpc方法的对象
            Dispatcher::Ptr _dispatcher; // 消息分发
            BaseServer::Ptr _rpcserver;  // 提供服务的服务器
        };

        class TopicServer
        {
        public:
            using Ptr = std::shared_ptr<TopicServer>;
            TopicServer(int port) : _topicmanager(std::make_shared<TopicManager>()), _dispatcher(std::make_shared<Dispatcher>())
            {
                auto req_rpc = std::bind(&TopicManager::onTopicOperate, _topicmanager.get(), std::placeholders::_1,
                                         std::placeholders::_2);
                auto shutcb = std::bind(&TopicManager::onShutdown, _topicmanager.get(), std::placeholders::_1);
                _dispatcher->registerCallback<TopicRequest>(MType::REQ_TOPIC, req_rpc);

                _topicrserver = ServerFactory::create(port);
                auto dpcher = std::bind(&Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1,
                                        std::placeholders::_2);
                _topicrserver->setMessageCallback(dpcher);
                _topicrserver->setCloseCallback(shutcb);
            }

            void start()
            {
                INFO_LOG("topic 服务中心开始运行！");
                _topicrserver->start();
            }

        private:
            TopicManager::Ptr _topicmanager;
            Dispatcher::Ptr _dispatcher;
            BaseServer::Ptr _topicrserver;
        };
    }
}
